package cn.mesmile.storage.entity;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author zb
 *  上传进度条反馈
 */
public class ProgressInputStream extends FilterInputStream {

    private UploadListener monitor;
    private long nread = 0;
    private long size = 0;


    /**
     * Constructs an object to monitor the progress of an input stream.
     *
     * @param message         Descriptive text to be placed in the dialog box
     *                        if one is popped up.
     * @param parentComponent The component triggering the operation
     *                        being monitored.
     * @param in              The input stream to be monitored.
     */
    public ProgressInputStream(InputStream in, UploadListener listener) {
        super(in);
        try {
            size = in.available();
        } catch (IOException ioe) {
            size = 0;
        }
        monitor = listener;
    }



    /**
     * Get the ProgressMonitor object being used by this stream. Normally
     * this isn't needed unless you want to do something like change the
     * descriptive text partway through reading the file.
     *
     * @return the ProgressMonitor object used by this object
     */
    public UploadListener getListener() {
        return monitor;
    }


    /**
     * Overrides <code>FilterInputStream.read</code>
     * to update the progress monitor after the read.
     */
    @Override
    public int read() throws IOException {
        int c = in.read();
        if (c >= 0) {
            notifyProcess(++nread);
        }
        return c;
    }


    /**
     * Overrides <code>FilterInputStream.read</code>
     * to update the progress monitor after the read.
     */
    @Override
    public int read(byte b[]) throws IOException {
        int nr = in.read(b);
        if (nr > 0) {
            notifyProcess(nread += nr);
        }

        return nr;
    }


    /**
     * Overrides <code>FilterInputStream.read</code>
     * to update the progress monitor after the read.
     */
    @Override
    public int read(byte b[], int off, int len) throws IOException {
        int nr = in.read(b, off, len);
        if (nr > 0) {
            notifyProcess(nread += nr);
        }
        return nr;
    }


    /**
     * Overrides <code>FilterInputStream.skip</code>
     * to update the progress monitor after the skip.
     */
    @Override
    public long skip(long n) throws IOException {
        long nr = in.skip(n);
        if (nr > 0) {
            notifyProcess(nread += nr);
        }
        return nr;
    }


    /**
     * Overrides <code>FilterInputStream.close</code>
     * to close the progress monitor as well as the stream.
     */
    @Override
    public void close() throws IOException {
        in.close();
    }


    /**
     * Overrides <code>FilterInputStream.reset</code>
     * to reset the progress monitor as well as the stream.
     */
    @Override
    public synchronized void reset() throws IOException {
        in.reset();
        nread = size - in.available();
    }

    private void notifyProcess(long read) {
        if (monitor != null) {
            monitor.onProgress((int) ((float) read * 100 / size));
        }
    }
}